﻿/*
 * Copyright 2009 José David Tuero Rodríguez

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 * */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AtmosCreator
{
    /// <summary>
    /// Business class for play control
    /// </summary>
    /// 
    class Play
    {
        /// <summary>
        /// Clock of play time
        /// </summary>
        private DateTime _playTime;

        /// <summary>
        /// PlayList of songs
        /// </summary>
        private SongsPlayList _songsPlayList;

        /// <summary>
        /// PlayList of videos
        /// </summary>
        private VideosPlayList _videosPlayList;

        /// <summary>
        /// PlayList of starting videos
        /// </summary>
        private VideosPlayList _startingVideosPlayList;

        /// <summary>
        /// PlayList of starting videos
        /// </summary>
        private VideosPlayList _endingVideosPlayList;

        /// <summary>
        /// PlayList of select the chosen one videos
        /// </summary>
        private VideosPlayList _selectChosenVideosPlayList;

        /// <summary>
        /// PlayList of chosen one videos
        /// </summary>
        private VideosPlayList _chosenVideosPlayList;

        /// <summary>
        /// Current media playing
        /// </summary>
        private string _currentMedia;

        /// <summary>
        /// Generator of random numbers
        /// </summary>
        private Random _randomGenerator;

        /// <summary>
        /// Instance of configuration class
        /// </summary>
        private Configuration _config;

        /// <summary>
        /// Is a video playing??
        /// </summary>
        private bool _videoPlaying=false;

        /// <summary>
        /// Has the game ended??
        /// </summary>
        private bool _gameEnded = false;

        /// <summary>
        /// Moment (in seconds) in which the chosen one must be selected
        /// </summary>
        private int _timeToSelectChosen;

        /// <summary>
        /// Has been the chosen one selected?
        /// </summary>
        private bool _chosenOneSelected=false;
        /// <summary>
        /// Is the game paused?
        /// </summary>
        private bool _gamePaused = false;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="game">Game used</param>
        public Play(string game)
        {
            _randomGenerator = new Random((int)DateTime.Now.Ticks);              
            _config = new Configuration(game);
            _songsPlayList = new SongsPlayList(AtmosCreator.Properties.Resources.GamesDirectory + "\\" + game + "\\" + AtmosCreator.Properties.Resources.SongDirectory);
            _videosPlayList = new VideosPlayList(AtmosCreator.Properties.Resources.GamesDirectory + "\\" + game + "\\" + AtmosCreator.Properties.Resources.VideoDirectory);
            _startingVideosPlayList = new VideosPlayList(AtmosCreator.Properties.Resources.GamesDirectory + "\\" + game + "\\" + AtmosCreator.Properties.Resources.StartVideoDirectory);
            _endingVideosPlayList = new VideosPlayList(AtmosCreator.Properties.Resources.GamesDirectory + "\\" + game + "\\" + AtmosCreator.Properties.Resources.EndVideoDirectory);
            _selectChosenVideosPlayList = new VideosPlayList(AtmosCreator.Properties.Resources.GamesDirectory + "\\" + game + "\\" + AtmosCreator.Properties.Resources.SelectChosenVideoDirectory);
            _chosenVideosPlayList = new VideosPlayList(AtmosCreator.Properties.Resources.GamesDirectory + "\\" + game + "\\" + AtmosCreator.Properties.Resources.ChosenVideoDirectory);
            _currentMedia = null;
            _timeToSelectChosen = _randomGenerator.Next(_config.MinChosen, _config.MaxChosen);
           
        }

        /// <summary>
        /// Method called to start the game  (not mandatory, only used to set the starting vid if avaliable)
        /// </summary>
        /// <returns>The filename which the media player must play. If no media is required to play the method will return the string "NothingToDo"</returns>
        public string StartGame()
        {
            return LaunchVideo(_startingVideosPlayList);
        }

        /// <summary>
        /// Advance one second in the clock
        /// </summary>
        /// <returns>The filename which the media player must play. 
        /// If no media is required to play the method will return the string "NothingToDo".
        /// If the game has ended the method will return "GameEnded", the form must end calling this method when "GameEnded" has been returned.</returns>
        public string AdvanceSecond()
        {
            if (_gamePaused)
            {
                return "NothingToDo";
            }
            else
            {
                if (!_gameEnded)
                {
                    _playTime = _playTime.AddSeconds(1);
                    //If a video is not playing
                    if (!_videoPlaying)
                    {
                        //We must select the chosen one?
                        if (!_chosenOneSelected && _timeToSelectChosen <= _playTime.TimeOfDay.TotalSeconds)
                        {
                            _chosenOneSelected = true;
                            //Launch the video
                            return LaunchVideo(_selectChosenVideosPlayList);
                        }
                        //Must a video start?
                        if (MustVideoStart())
                        {
                            return _currentMedia;
                        }
                        //Something is playing?
                        if (_currentMedia != null)
                        {
                            return "NothingToDo";
                        }
                        //A new songs starts to play
                        return LaunchSong(_songsPlayList);
                    }
                    return "NothingToDo";
                }
                return "GameEnded";
            }
        }

        /// <summary>
        /// This method constrols if a video must play
        /// </summary>
        /// <returns>true if the video located at _currentMedia must start, false if not</returns>
        private bool MustVideoStart()
        {
            //End video
            if (_playTime.TimeOfDay.TotalSeconds >= _config.GameTime)
            {
                LaunchVideo(_endingVideosPlayList);
                _gameEnded = true;
                return true;
            }
            //Normal video
            if (_playTime.Second % _config.VidSeconds == 0)
            {
                //A video must show
                if (_randomGenerator.Next(100) < _config.VidPer)
                {
                    //A chosen one video?
                    if (_randomGenerator.Next(100) < _config.PerChosen && _chosenOneSelected)
                    {
                        LaunchVideo(_chosenVideosPlayList);
                        return true;
                    }
                    //A normal video
                    LaunchVideo(_videosPlayList);                  
                    return true;
                }
            }
            return false;
        }




        /// <summary>
        /// This method must be called by the presentation layer when a playing media file has ended
        /// </summary>
        public void EndMedia()
        {
            _currentMedia = null;
            _videoPlaying = false;
        }

        /// <summary>
        /// get method
        /// </summary>
        public DateTime PlayTime
        {
            get
            {
                return _playTime;
            }
        }

        /// <summary>
        /// get method
        /// </summary>
        public bool StrechVideo
        {
            get
            {
                return _config.Stretch;
            }
        }

        /// <summary>
        /// Method used to launch a song from a SongsPlayList, it sets the value of _currentMedia and returns the value 
        /// asigned to _currentMedia
        /// </summary>
        /// <param name="playList">Playlist to use</param>
        /// <returns>The song to be played</returns>
        private string LaunchSong(SongsPlayList playList)
        {
            if (playList.Songs.Length > 0)
            {
                _currentMedia=playList.Songs[_randomGenerator.Next(playList.Songs.Length)];
                return _currentMedia;
            }
            return "NothingToDo";
        }


        /// <summary>
        /// Method used to launch a video from a VideosPlayList, it sets the value of _currentMedia and returns the value 
        /// asigned to _currentMedia
        /// </summary>
        /// <param name="playList">Playlist to use</param>
        /// <returns>The video to be played</returns>
        private string LaunchVideo(VideosPlayList playList)
        {
            if (playList.Videos.Length > 0)
            {
                _videoPlaying = true;
                _currentMedia = playList.Videos[_randomGenerator.Next(playList.Videos.Length)];
                return _currentMedia;
            }
            //Empty playlist so nothing to do
            return "NothingToDo";
        }
        /// <summary>
        /// Method used to pause/re-run the game (if game running then pause it, if paused then re-run it)
        /// </summary>
        public void Pause()
        {
            _gamePaused = !_gamePaused;
        }

    }
}
